﻿using System;
using System.Collections.Generic;
using System.Text;

using CommunicatorAPI;

namespace ClickToCall.ClickToCallToolbar.Builders
{
    public class MessengerInstanceException : Exception
    {
        public MessengerInstanceException(object thrower, Exception e) :
            base("Messenger Load Error", e)
        {
        }
    }

    public class MessengerInstance
    {
        private Messenger _messenger;
        private MessengerInstance() 
        {
            if (System.Diagnostics.Process.GetProcessesByName("communicator").Length > 0)
                _messenger = new Messenger();
            else
                throw new MessengerInstanceException(this, new Exception("A local instance of Office Communicator 2007 is not available."));
        }
        private sealed class Creator
        {
            private static readonly MessengerInstance instance = new MessengerInstance();

            public static MessengerInstance CreatorInstance
            {
                get { return instance; }
            }
        }

        public static MessengerInstance Instance
        {
            get { return Creator.CreatorInstance; }
        }

        public Messenger Messenger
        {
            get { return _messenger; }
        }
    }

    public class CommunicatorContactFilter : ContactFilter
    {
        public CommunicatorContactFilter(bool useHome, bool useMobile, bool useBusiness, bool useOther)
        {
            this.UseHome = useHome;
            this.UseMobile = useMobile;
            this.UseBusiness = useBusiness;
            this.UseOther = useOther;
        }
        public readonly bool UseHome;
        public readonly bool UseMobile;
        public readonly bool UseBusiness;
        public readonly bool UseOther;
    }

    public class CommunicatorContactBuilder : ContactBuilder
    {
        private CommunicatorContactFilter _filter;
        public CommunicatorContactBuilder(CommunicatorContactFilter filter)
            : base(filter)
        {
            _filter = filter;
        }
        /// <summary>
        /// Return a ContactCollection of Contacts found within a local instance of Office Communicator 2007
        /// </summary>
        /// <returns>ContactCollection</returns>
        /// <exception cref="ContactBuilderException">Thrown if an error occurs while building contact list.</exception> 
        public override ContactCollection GetContacts()
        {
            ContactCollection cc = new ContactCollection();
            //If communicator is not installed, then do not attempt to process contacts
            if (!IsBuilderAvailable(this.AppName))
                return cc;

            Messenger _communicator;
            try
            {
                _communicator = MessengerInstance.Instance.Messenger;

                if (_communicator.MyStatus == MISTATUS.MISTATUS_OFFLINE ||
                    _communicator.MyStatus == MISTATUS.MISTATUS_UNKNOWN)
                    return cc;
                IMessengerContacts myContacts = (IMessengerContacts)_communicator.MyContacts;
                if (myContacts != null && myContacts.Count > 0)
                {
                    PhoneNumbers pns;
                    foreach (IMessengerContact c in myContacts)
                    {
                        pns = new PhoneNumbers();
                        if (_filter.UseHome)     pns.HomeTelephoneNumber = GetCommunicatorContactPhoneNumber(c, MPHONE_TYPE.MPHONE_TYPE_HOME);
                        if (_filter.UseMobile)   pns.MobileTelephoneNumber = GetCommunicatorContactPhoneNumber(c, MPHONE_TYPE.MPHONE_TYPE_MOBILE);
                        if (_filter.UseBusiness) pns.BusinessTelephoneNumber = GetCommunicatorContactPhoneNumber(c, MPHONE_TYPE.MPHONE_TYPE_WORK);
                        if (_filter.UseOther)    pns.OtherTelephoneNumber = GetCommunicatorContactPhoneNumber(c, MPHONE_TYPE.MPHONE_TYPE_CUSTOM);
                        cc.Add(new Contact(pns, c.FriendlyName, c.SigninName, c.SigninName));
                    }
                }
            }
            catch (MessengerInstanceException)
            {
                //communicator is not running, leave it alone
            }
            catch(Exception e)
            {
                throw new ContactBuilderException(this, e);
            }
            finally
            {
                _communicator = null; 
            }
            return cc;
        }

        public override string AppName
        {
            get { return "communicator.exe"; }
        }

        private string GetCommunicatorContactPhoneNumber(IMessengerContact contact, MPHONE_TYPE mpType)
        {
            try
            {
                return contact.get_PhoneNumber(mpType);
            }
            catch (System.Runtime.InteropServices.COMException)
            {
                return string.Empty;
            }
        }
    }
}
